/*
 * Copyright 2012 Finbudget.com
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package finbudgettable.client.ui.grid.cell;

import com.google.gwt.cell.client.AbstractEditableCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.Constants;
import com.google.gwt.regexp.shared.RegExp;

import java.util.HashMap;
import java.util.Map;

/**
 * Override manipulations with viewData to have the abilities to clear a viewData cache.
 */
public abstract class AbstractEditableGridCell<C, V> extends AbstractEditableCell<C, V>
        implements CanBeReadonly, HasMultilineStyle, HasViewDataCache {

    interface Strings extends Constants {
        @DefaultStringValue("[\\wА-Яа-я]+")
        String validSymbolsRE();
    }

    private static final Strings STRINGS = GWT.create(Strings.class);
    private static final RegExp ABC_RE = RegExp.compile(STRINGS.validSymbolsRE());

    private boolean readonly;
    private boolean parentReadonly;
    private boolean multilineStyle;
    private final Map<Object, V> viewDataCache = new HashMap<Object, V>();

    public AbstractEditableGridCell(String... consumedEvents) {
        super(consumedEvents);
    }

    @Override
    public V getViewData(Object key) {
        if (key == null) {
            return null;
        }
        return viewDataCache.get(key);
    }

    @Override
    public void clearViewData(Object key) {
        if (key != null) {
            viewDataCache.remove(key);
        }
    }

    @Override
    public void setViewData(Object key, V viewData) {
        if (key == null) {
            return;
        }
        if (viewData == null) {
            clearViewData(key);
        } else {
            viewDataCache.put(key, viewData);
        }
    }

    /**
     * Clears a cell's viewData cache
     */
    public void clearViewDataCache() {
        viewDataCache.clear();
    }


    public boolean isParentReadonly() {
        return parentReadonly;
    }

    public void setParentReadonly(boolean parentReadonly) {
        this.parentReadonly = parentReadonly;
    }

    public boolean isReadonly() {
        return readonly || isParentReadonly();
    }

    public void setReadonly(boolean readonly) {
        this.readonly = readonly;
    }

    public boolean isMultilineStyle() {
        return multilineStyle;
    }

    public void setMultilineStyle(boolean multilineStyle) {
        this.multilineStyle = multilineStyle;
    }

    protected String getStringFromCharCode(int charCode) {
        char symbol = Character.toChars(charCode)[0];
        return new String(new char[]{symbol});
    }

    protected boolean isValidChar(String newValue) {
        return ABC_RE.test(newValue);
    }
}

